/**
 * 资源优化工具类
 * 负责应用中各种资源的优化，包括图片、字体、音频等
 */

import performanceConfig from '../config/performance.js';

class ResourceOptimizer {
  constructor() {
    this.config = performanceConfig;
    this.imageCache = new Map();
    this.preloadedResources = new Set();
    this.lazyLoadImages = new Set();
    this.observer = null;
    this.init();
  }
  
  /**
   * 初始化资源优化器
   */
  init() {
    // 初始化图片懒加载
    if (this.config.resources.image.lazyLoad) {
      this.initLazyLoad();
    }
    
    // 清理过期缓存
    this.cleanExpiredCache();
    
    // 监听应用事件
    this.listenAppEvents();
  }
  
  /**
   * 初始化懒加载
   */
  initLazyLoad() {
    // 使用IntersectionObserver实现懒加载
    if (typeof IntersectionObserver !== 'undefined') {
      this.observer = new IntersectionObserver((entries) => {
        entries.forEach(entry => {
          if (entry.isIntersecting) {
            const img = entry.target;
            const originalSrc = img.getAttribute('data-src');
            
            if (originalSrc) {
              this.loadImage(originalSrc).then(url => {
                img.src = url;
                img.removeAttribute('data-src');
                this.observer.unobserve(img);
                this.lazyLoadImages.delete(img);
              });
            }
          }
        });
      }, {
        rootMargin: `${this.config.cache.image.preloadDistance}px`
      });
    }
  }
  
  /**
   * 注册懒加载图片
   * @param {HTMLImageElement} img - 图片元素
   * @param {string} src - 图片源
   */
  registerLazyLoadImage(img, src) {
    if (!this.config.resources.image.lazyLoad || !this.observer) {
      img.src = src;
      return;
    }
    
    // 设置占位符
    img.src = this.getPlaceholderImage();
    img.setAttribute('data-src', src);
    this.lazyLoadImages.add(img);
    this.observer.observe(img);
  }
  
  /**
   * 获取占位符图片
   * @returns {string} 占位符图片URL
   */
  getPlaceholderImage() {
    // 创建一个纯色占位符
    const color = this.config.resources.image.placeholderColor;
    return `data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100%25' height='100%25'%3E%3Crect width='100%25' height='100%25' fill='${encodeURIComponent(color)}'/%3E%3C/svg%3E`;
  }
  
  /**
   * 加载图片
   * @param {string} src - 图片源
   * @returns {Promise<string>} 优化后的图片URL
   */
  async loadImage(src) {
    // 检查缓存
    if (this.imageCache.has(src)) {
      const cached = this.imageCache.get(src);
      if (!this.isExpired(cached.timestamp, this.config.cache.image.maxCacheAge)) {
        cached.lastAccess = Date.now();
        return cached.url;
      } else {
        // 过期，移除缓存
        this.imageCache.delete(src);
      }
    }
    
    try {
      // 对于网络图片进行优化
      if (src.startsWith('http')) {
        const optimizedUrl = await this.optimizeImage(src);
        this.cacheImage(src, optimizedUrl);
        return optimizedUrl;
      } else {
        // 本地图片直接缓存
        this.cacheImage(src, src);
        return src;
      }
    } catch (error) {
      console.error('图片加载失败:', error);
      return src; // 失败时返回原图
    }
  }
  
  /**
   * 优化图片
   * @param {string} src - 图片源
   * @returns {Promise<string>} 优化后的图片URL
   */
  async optimizeImage(src) {
    // 在实际应用中，这里可以调用图片压缩服务或使用canvas进行压缩
    // 由于在uni-app中，我们使用简单的实现
    
    if (!this.config.resources.image.enabled) {
      return src;
    }
    
    // 对于网络图片，可以添加压缩参数
    // 这里模拟优化过程
    const isWebpSupported = this.checkWebpSupport();
    
    // 如果支持webp，可以转换为webp格式
    if (isWebpSupported && !src.includes('.webp') && !src.includes('data:image')) {
      // 实际项目中可以使用云存储服务的图片处理能力
      // 这里仅作示例
    }
    
    return src;
  }
  
  /**
   * 检查WebP支持
   * @returns {boolean} 是否支持WebP
   */
  checkWebpSupport() {
    // 在浏览器环境中检查WebP支持
    // 在uni-app中，通常可以安全地假设支持
    return true;
  }
  
  /**
   * 缓存图片
   * @param {string} src - 原始源
   * @param {string} url - 缓存的URL
   */
  cacheImage(src, url) {
    // 检查缓存大小，超出限制时清理最旧的缓存
    if (this.imageCache.size >= this.config.cache.image.maxCacheSize) {
      this.evictOldestFromCache();
    }
    
    this.imageCache.set(src, {
      url,
      timestamp: Date.now(),
      lastAccess: Date.now()
    });
  }
  
  /**
   * 从缓存中移除最旧的项
   */
  evictOldestFromCache() {
    let oldestKey = null;
    let oldestTime = Infinity;
    
    for (const [key, value] of this.imageCache.entries()) {
      if (value.timestamp < oldestTime) {
        oldestTime = value.timestamp;
        oldestKey = key;
      }
    }
    
    if (oldestKey) {
      this.imageCache.delete(oldestKey);
    }
  }
  
  /**
   * 检查是否过期
   * @param {number} timestamp - 时间戳
   * @param {number} maxAge - 最大年龄
   * @returns {boolean} 是否过期
   */
  isExpired(timestamp, maxAge) {
    return Date.now() - timestamp > maxAge;
  }
  
  /**
   * 预加载资源
   * @param {Array} resources - 资源列表
   * @returns {Promise} 预加载完成的Promise
   */
  async preloadResources(resources) {
    if (!this.config.network.prefetch.enabled) {
      return;
    }
    
    const promises = resources.map(resource => {
      if (!this.preloadedResources.has(resource.url)) {
        this.preloadedResources.add(resource.url);
        
        switch (resource.type) {
          case 'image':
            return this.preloadImage(resource.url);
          case 'script':
            return this.preloadScript(resource.url);
          case 'style':
            return this.preloadStyle(resource.url);
          case 'font':
            return this.preloadFont(resource.url);
          default:
            return Promise.resolve();
        }
      }
      return Promise.resolve();
    });
    
    return Promise.all(promises);
  }
  
  /**
   * 预加载图片
   * @param {string} url - 图片URL
   * @returns {Promise} 预加载完成的Promise
   */
  preloadImage(url) {
    return new Promise((resolve, reject) => {
      const img = new Image();
      img.onload = () => resolve(url);
      img.onerror = reject;
      img.src = url;
    });
  }
  
  /**
   * 预加载脚本
   * @param {string} url - 脚本URL
   * @returns {Promise} 预加载完成的Promise
   */
  preloadScript(url) {
    return new Promise((resolve, reject) => {
      const script = document.createElement('script');
      script.src = url;
      script.onload = () => resolve(url);
      script.onerror = reject;
      script.setAttribute('preload', 'true');
      document.head.appendChild(script);
    });
  }
  
  /**
   * 预加载样式
   * @param {string} url - 样式URL
   * @returns {Promise} 预加载完成的Promise
   */
  preloadStyle(url) {
    return new Promise((resolve, reject) => {
      const link = document.createElement('link');
      link.rel = 'stylesheet';
      link.href = url;
      link.onload = () => resolve(url);
      link.onerror = reject;
      document.head.appendChild(link);
    });
  }
  
  /**
   * 预加载字体
   * @param {string} url - 字体URL
   * @returns {Promise} 预加载完成的Promise
   */
  preloadFont(url) {
    if (!this.config.resources.font.enabled || !this.config.resources.font.preloadCriticalFonts) {
      return Promise.resolve();
    }
    
    return new Promise((resolve) => {
      const link = document.createElement('link');
      link.rel = 'preload';
      link.as = 'font';
      link.href = url;
      link.crossOrigin = 'anonymous';
      link.onload = () => resolve(url);
      document.head.appendChild(link);
    });
  }
  
  /**
   * 压缩图片
   * @param {string} src - 图片源
   * @param {Object} options - 压缩选项
   * @returns {Promise<string>} 压缩后的图片URL
   */
  compressImage(src, options = {}) {
    const config = this.config.resources.image;
    
    const { 
      quality = config.quality,
      maxWidth = config.maxWidth,
      maxHeight = config.maxHeight
    } = options;
    
    return new Promise((resolve) => {
      // 在浏览器环境中，使用canvas压缩图片
      // 在uni-app中，我们需要使用其API
      #ifdef H5
      const img = new Image();
      img.onload = function() {
        const canvas = document.createElement('canvas');
        let width = img.width;
        let height = img.height;
        
        // 计算缩放比例
        if (width > maxWidth) {
          const ratio = maxWidth / width;
          width = maxWidth;
          height = height * ratio;
        }
        
        if (height > maxHeight) {
          const ratio = maxHeight / height;
          height = maxHeight;
          width = width * ratio;
        }
        
        canvas.width = width;
        canvas.height = height;
        
        const ctx = canvas.getContext('2d');
        ctx.drawImage(img, 0, 0, width, height);
        
        // 压缩并转换为base64
        const compressedDataUrl = canvas.toDataURL('image/jpeg', quality);
        resolve(compressedDataUrl);
      };
      img.src = src;
      #else
      // 在非H5环境中，返回原图
      // 实际项目中可以使用uni-app的图片处理API
      resolve(src);
      #endif
    });
  }
  
  /**
   * 清理过期缓存
   */
  cleanExpiredCache() {
    const now = Date.now();
    const maxAge = this.config.cache.image.maxCacheAge;
    
    for (const [key, value] of this.imageCache.entries()) {
      if (now - value.timestamp > maxAge) {
        this.imageCache.delete(key);
      }
    }
  }
  
  /**
   * 监听应用事件
   */
  listenAppEvents() {
    // 在uni-app中监听应用生命周期
    uni.onAppShow(() => {
      // 应用显示时恢复资源加载
      this.resumeResourceLoading();
    });
    
    uni.onAppHide(() => {
      // 应用隐藏时暂停非关键资源加载
      this.pauseNonCriticalResourceLoading();
    });
    
    uni.onNetworkStatusChange((res) => {
      // 监听网络状态变化
      if (!res.isConnected) {
        // 网络断开时，使用离线模式
        this.switchToOfflineMode();
      } else {
        // 网络恢复时，重新连接
        this.reconnectResources();
      }
    });
  }
  
  /**
   * 恢复资源加载
   */
  resumeResourceLoading() {
    // 继续预加载资源
    if (this.pausedPreloads) {
      this.preloadResources(this.pausedPreloads);
      this.pausedPreloads = null;
    }
  }
  
  /**
   * 暂停非关键资源加载
   */
  pauseNonCriticalResourceLoading() {
    // 在应用隐藏时，可以暂停预加载等非关键资源
    // 这里简化处理
  }
  
  /**
   * 切换到离线模式
   */
  switchToOfflineMode() {
    // 使用缓存的资源
  }
  
  /**
   * 重新连接资源
   */
  reconnectResources() {
    // 网络恢复时，刷新必要的资源
  }
  
  /**
   * 获取缓存统计信息
   * @returns {Object} 缓存统计
   */
  getCacheStats() {
    return {
      imageCacheSize: this.imageCache.size,
      maxImageCacheSize: this.config.cache.image.maxCacheSize,
      preloadedResourcesCount: this.preloadedResources.size,
      lazyLoadedImagesCount: this.lazyLoadImages.size
    };
  }
  
  /**
   * 清理所有缓存
   */
  clearAllCache() {
    this.imageCache.clear();
    this.preloadedResources.clear();
  }
}

// 导出单例
const resourceOptimizer = new ResourceOptimizer();
export default resourceOptimizer;

// 导出工具函数
export const imageUtils = {
  /**
   * 生成图片缩略图
   * @param {string} url - 原图URL
   * @param {number} width - 缩略图宽度
   * @param {number} height - 缩略图高度
   * @returns {string} 缩略图URL
   */
  generateThumbnail(url, width = 200, height = 200) {
    // 实际项目中，这里可以调用图片服务生成缩略图
    // 这里仅作示例
    return url;
  },
  
  /**
   * 批量预加载图片
   * @param {Array<string>} urls - 图片URL数组
   * @returns {Promise} 预加载完成的Promise
   */
  preloadImages(urls) {
    return resourceOptimizer.preloadResources(
      urls.map(url => ({ type: 'image', url }))
    );
  },
  
  /**
   * 懒加载图片元素
   * @param {Array<HTMLImageElement>} images - 图片元素数组
   */
  lazyLoadImages(images) {
    images.forEach(img => {
      if (img.getAttribute('data-src')) {
        resourceOptimizer.registerLazyLoadImage(img, img.getAttribute('data-src'));
      }
    });
  }
};

// 导出性能优化建议
export const resourceOptimizationTips = {
  /**
   * 获取图片优化建议
   * @param {Object} imageInfo - 图片信息
   * @returns {Array<string>} 优化建议
   */
  getImageOptimizationTips(imageInfo) {
    const tips = [];
    const config = performanceConfig.resources.image;
    
    if (imageInfo.width > config.maxWidth || imageInfo.height > config.maxHeight) {
      tips.push(`图片尺寸过大，建议压缩至${config.maxWidth}x${config.maxHeight}以内`);
    }
    
    if (imageInfo.format && imageInfo.format !== 'webp' && resourceOptimizer.checkWebpSupport()) {
      tips.push('建议使用WebP格式以减小图片体积');
    }
    
    if (imageInfo.size && imageInfo.size > 500 * 1024) { // 大于500KB
      tips.push('图片体积过大，建议进一步压缩');
    }
    
    return tips;
  },
  
  /**
   * 获取资源加载优化建议
   * @param {Object} loadInfo - 加载信息
   * @returns {Array<string>} 优化建议
   */
  getResourceLoadingTips(loadInfo) {
    const tips = [];
    
    if (loadInfo.totalSize > 10 * 1024 * 1024) { // 大于10MB
      tips.push('初始加载资源过大，建议使用代码分割和按需加载');
    }
    
    if (loadInfo.slowResources && loadInfo.slowResources.length > 0) {
      tips.push(`存在${loadInfo.slowResources.length}个加载较慢的资源，建议优化或使用CDN`);
    }
    
    return tips;
  }
};